
/* description: Parses and executes mathematical expressions. */

%{

    var root = undefined;
    function debug(str) {
        //console.log(str);
    }
%}
/* lexical grammar */

%lex
%%

\s+                   /* skip whitespace */
("true"|"false")      {debug("Boolean");return "Boolean"}
(["][a-zA-Z0-9.]+["]) {debug("String");return "String"}
=
[0-9]+("."[0-9]+)?\b  {debug("Number");return "Number"}

([#@$][a-zA-Z0-9.]+)  {debug("VARIABLE");return "VARIABLE"}
/****算数运算符号**/
"*"                   {debug("*"); return "*"}
"/"                   {debug("/"); return "/"}
"-"                   {debug("-"); return "-"}
"+"                   {debug("+"); return "+"}
"%"                   {debug("%"); return "%"}
/***逻辑运算符****/
"&&"                  {debug("&&"); return "&&"}
"||"                  {debug("||"); return "||"}
"!"                   {debug("!");  return "!"}

"("                   {debug("("); return "("}
")"                   {debug(")"); return ")"}
"￥"                   {debug("￥"); return "EOF"}
<<EOF>>               return 'EOF'
.                     return 'INVALID'

/lex

/* operator associations and precedence */

%left '+' '-'
%left '*' '/'
%left '^'
%right '!'
%right '%'
%left UMINUS

%start expressions

%% /* language grammar */

expressions
    : e EOF
        { root = $1;
          return root }
    ;

e
    : e '+' e
        {$$ = new ExpNode("+",yylineno,yyleng,[$1,$3]);}
    | e '-' e
        {$$ = new ExpNode("-",yylineno,yyleng,[$1,$3]);}
    | e '*' e
        {$$ = new ExpNode("*",yylineno,yyleng,[$1,$3]);}
    | e '/' e
        {$$ = new ExpNode("/",yylineno,yyleng,[$1,$3]);}
    | e '!'
        {$$ = new ExpNode("!",yylineno,yyleng,[$1,$3]);}
    | e '%'
        {$$ = new ExpNode("%",yylineno,yyleng,[$1,$3]);}
    | '-' e %prec UMINUS
        {$$ = new ExpNode("-",yylineno,yyleng,[$2]);}
    | '(' e ')'
        {$$ = new ExpNode("()",yylineno,yyleng,[new OpNode("(",yylineno,yyleng),$2,new OpNode(")",yylineno,yyleng)]);}
    | Number
        {$$ = new NumberNode(yylineno,yyleng,new NodeValue("number",parseInt($1)));}
    | VARIABLE
        {$$ = new IDNode("VARIABLE",yylineno,yyleng,$1);}
    | String
        {$$ = new StringNode(yylineno,yyleng,new NodeValue("string",$1.substring(1,$1.length-1)));}
    | Boolean
        {$$ = new BooleanNode(yylineno,yyleng,new NodeValue("boolean",$1 === "true"?true:false));}
    ;

